home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
amiga
/
gui
/
prcgntn1.lha
/
Precognition
/
source
/
ListBrowser.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-23
|
12KB
|
480 lines
/* ==========================================================================
**
** ListBrowser.c
**
** ⌐1991 WILLISoft
**
** ==========================================================================
*/
#include <string.h>
#include "minmax.h"
#include "ListBrowser.h"
#include "ListBrowserClass.h"
#include "EmbossedGadgetClass.h"
#include "precognition.h"
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include "amigamem.h"
#define CHAR_WIDTH 8 /* Width of Topaz 80 font.*/
#define CHAR_HEIGHT 9 /* Height of Topaz 80 font.*/
#define BROWSER_ENTRY_HEIGHT (CHAR_HEIGHT + 1)
#define BORDER_WIDTH 3
#define BASELINE 8
#define isSelected(q) (q & ENTRY_SELECTED)
const StringList *ListBrowser_StringList_of( ListBrowser *self )
{
return &self->List;
}
void ListBrowser_Init( ListBrowser *self,
PIXELS LeftEdge,
PIXELS TopEdge,
PIXELS Width,
PIXELS Height,
pcg_3DPens Pens,
BOOL SelectMany )
{
EmbossedGadget_Init( &self->eg, LeftEdge, TopEdge, 0, 0,
GADGHNONE, RELVERIFY, BOOLGADGET, Pens, NULL );
self->eg.isa = ListBrowserClass();
self->SelectMany = SelectMany;
self->YOffset = 0;
SetLocation( self, LeftEdge, TopEdge );
SetSize( self, Width, Height );
/* Initialize List structure... */
StringList_Init( &self->List, TRUE );
}
void ListBrowser_CleanUp( ListBrowser *self )
{
StringList *sl;
StringList_CleanUp( StringList_of(self) );
EmbossedGadget_CleanUp( self );
}
Point ListBrowser_AskSize( ListBrowser *self,
PIXELS Width,
PIXELS Height )
{
Point size;
short nCols, nRows;
nCols = ( Width-BORDER_WIDTH*2 ) / CHAR_WIDTH;
nRows = ( Height-BORDER_WIDTH*2 ) / BROWSER_ENTRY_HEIGHT;
nCols = MAX( nCols, 5 );
nRows = MAX( nRows, 5 );
size.x = nCols*CHAR_WIDTH + BORDER_WIDTH*2;
size.y = nRows*BROWSER_ENTRY_HEIGHT + BORDER_WIDTH*2;
return size;
}
Point ListBrowser_SetSize( ListBrowser *self,
PIXELS Width,
PIXELS Height )
{
Point size;
size = AskSize( self, Width, Height );
Forbid(); /* Don't want Intuition looking at these while we modify em. */
self->eg.Size = size;
self->eg.g.Width = size.x - BORDER_WIDTH*2;
self->eg.g.Height = size.y - BORDER_WIDTH*2;
pcg_Init3DBox( self->eg.BoxBorder,
-BORDER_WIDTH, -BORDER_WIDTH,
size.x, size.y,
self->eg.Pens.BrightPen, self->eg.Pens.DarkPen,
self->eg.BoxBorder->BottomRight.NextBorder );
Permit();
self->nColumns = ( size.x-BORDER_WIDTH*2 ) / CHAR_WIDTH;
self->nRows = ( size.y-BORDER_WIDTH*2 ) / BROWSER_ENTRY_HEIGHT;
return size;
}
Point ListBrowser_SetLocation( ListBrowser *self,
PIXELS LeftEdge,
PIXELS TopEdge )
{
Point location;
Forbid();
self->eg.Location.x = LeftEdge;
self->eg.Location.y = TopEdge;
self->eg.g.LeftEdge = LeftEdge + BORDER_WIDTH;
self->eg.g.TopEdge = TopEdge + BORDER_WIDTH;
Permit();
return location;
}
USHORT ListBrowser_SetYOffset( ListBrowser *self,
USHORT YOffset )
{
SHORT MaxY;
MaxY = MAX( self->List.nEntries-self->nRows, 0 );
self->YOffset = MIN( YOffset, MaxY );
return self->YOffset;
}
#define DESELECT_ALL(b) ListBrowser_SelectAll(b, FALSE)
void ListBrowser_SelectAll( ListBrowser *self, BOOL Select )
/* Selects or deselects everything in the list. */
{
USHORT i;
for (i=0; i<self->List.nEntries; i++)
{
if (Select)
self->List.Qualifiers[i] |= ENTRY_SELECTED;
else
self->List.Qualifiers[i] &= (UBYTE) ~ENTRY_SELECTED;
}
}
void ListBrowser_SelectString( ListBrowser *self,
USHORT i,
BOOL Select )
{
if ((! self->SelectMany) && (Select))
DESELECT_ALL( self );
if (Select)
self->List.Qualifiers[i] |= ENTRY_SELECTED;
else
self->List.Qualifiers[i] &= ~ENTRY_SELECTED;
}
void ListBrowser_DrawEntry( ListBrowser *self,
RastPort *RPort,
USHORT index )
{
USHORT count, X, Y, Xend, Yend;
UBYTE qual, succ, pred;
char **Entries;
UBYTE *Qualifiers;
pcg_3DPens pens;
Entries = self->List.Entries;
Qualifiers = self->List.Qualifiers;
X = self->eg.Location.x + BORDER_WIDTH;
Y = self->eg.Location.y + BORDER_WIDTH
+ (index-self->YOffset)*BROWSER_ENTRY_HEIGHT;
Xend = X + self->eg.g.Width-1;
Yend = Y + BROWSER_ENTRY_HEIGHT;
pens = self->eg.Pens;
SetDrMd( RPort, JAM1 );
/* Clear the entry. */
SetAPen( RPort, pens.BackPen );
RectFill( RPort, X, Y, Xend, Yend );
qual = Qualifiers[index];
if (index)
pred = Qualifiers[index-1];
else
pred = 0;
if (index+1 < self->List.nEntries)
succ = Qualifiers[index+1];
else
succ = 0;
if (qual & ENTRY_SPECIAL)
SetAPen( RPort, pens.FrontPen+1 );
else
SetAPen( RPort, pens.FrontPen );
Move( RPort, X+1, Y+BASELINE );
count = strlen( Entries[index] );
count = MIN( self->nColumns, count );
Text( RPort, Entries[index], count );
if (isSelected(qual))
{
SetDrMd( RPort, COMPLEMENT );
/* Draw 3D lines. */
RectFill( RPort, X, Y, Xend, Yend );
SetDrMd( RPort, JAM1 );
SetAPen( RPort, pens.DarkPen );
Move( RPort, X, Yend );
Draw( RPort, X, Y );
SetAPen( RPort, pens.BrightPen ); /* Right side bar. */
Move( RPort, Xend, Y );
Draw( RPort, Xend, Yend );
}
/* Draw top bar. */
if (( (!isSelected(pred)) && isSelected(qual)))
/* previous is not selected, entry is */
{
SetAPen( RPort, pens.DarkPen );
Move( RPort, X, Y );
Draw( RPort, Xend, Y );
}
else if (isSelected(pred) && (!isSelected(qual)))
/* previous is selected, entry is not */
{
SetAPen( RPort, pens.BrightPen );
Move( RPort, X, Y );
Draw( RPort, Xend, Y );
}
/* Draw bottom bar */
if ((!isSelected(succ)) && isSelected(qual))
/* successor is not selected, entry is */
{
SetAPen( RPort, pens.BrightPen );
Move( RPort, X, Yend );
Draw( RPort, Xend, Yend );
}
else if (isSelected(succ) && (!isSelected(qual)))
/* successor is selected, entry is not */
{
SetAPen( RPort, pens.DarkPen );
Move( RPort, X, Yend );
Draw( RPort, Xend, Yend );
}
}
void ListBrowser_Render( ListBrowser *self,
RastPort *RPort )
{
USHORT X, Y, Xend, Yend;
USHORT i, j;
X = self->eg.g.LeftEdge;/* + BORDER_WIDTH;*/
Y = self->eg.g.TopEdge; /* + BORDER_WIDTH;*/
Xend = X + self->eg.g.Width-1;
Yend = Y + self->eg.g.Height-1;
DrawBorder( RPort, self->eg.BoxBorder, self->eg.g.LeftEdge, self->eg.g.TopEdge );
/* Clear the display area. */
SetDrMd( RPort, JAM1 );
SetAPen( RPort, self->eg.Pens.BackPen );
RectFill( RPort, X, Y, Xend, Yend );
/* Display the list */
for( j=0, i=self->YOffset; j<self->nRows; j++, i++)
{
if (i>=self->List.nEntries) break;
ListBrowser_DrawEntry( self, RPort, i );
}
}
void ListBrowser_ChangeHighlight( ListBrowser *self,
USHORT new_highlighted_entry, /* index */
RastPort *RPort )
{
USHORT i, j;
UBYTE *Qualifiers;
/* Display the list */
Qualifiers = self->List.Qualifiers;
/* Deselect the old one. */
i = self->YOffset;
for (j=0; j<self->nRows; j++, i++)
{
if (i >= self->List.nEntries) break;
if (isSelected(Qualifiers[i]) )
{
/* If this is the old highlight */
Qualifiers[i] &= ~ENTRY_SELECTED;
ListBrowser_DrawEntry( self, RPort, i );
}
}
Qualifiers[new_highlighted_entry] |= ENTRY_SELECTED;
if ((new_highlighted_entry - self->YOffset >= 0) &&
(new_highlighted_entry - self->YOffset < self->nRows))
ListBrowser_DrawEntry( self, RPort, new_highlighted_entry );
}
void ListBrowser_Refresh( ListBrowser *self )
{
struct pcgWindow *window;
window = InteractorWindow( self );
Render( self, window->Window->RPort );
}
void ListBrowser_AddString( ListBrowser *self,
char *entry,
UBYTE qualifier )
{
if ((! self->SelectMany) && isSelected(qualifier))
DESELECT_ALL( self );
/* This new entry is selected, so all others must be deselected. */
StringList_AddString( &self->List, entry, qualifier );
}
BOOL ListBrowser_DeleteString( ListBrowser *self, USHORT i )
{
BOOL result;
StringList *sl;
/*DUMPWAIT("ListBrowser_DeleteString\n");*/
sl = StringList_of(self);
result = StringList_DeleteString( sl, i );
ListBrowser_SetYOffset( self, self->YOffset );
/*DUMPWAIT("end ListBrowser_DeleteString\n");*/
return result;
}
BOOL ListBrowser_DeleteAllStrings( ListBrowser *self )
{
BOOL result;
result = StringList_DeleteAllStrings( &self->List );
ListBrowser_SetYOffset( self, self->YOffset );
return result;
}
#define CLAIM_EVENT(b,e) (&b->eg.g == (Gadget *) e->IAddress)
USHORT ListBrowser_Respond( ListBrowser *self,
IntuiMessage *Event )
{
Point Mouse;
USHORT entry_no;
USHORT response = 0;
UBYTE qual;
switch (Event->Class)
{
case REFRESHWINDOW:
ListBrowser_Render( self, Event->IDCMPWindow->RPort );
response = RESPONDED;
break;
case GADGETUP:
if (CLAIM_EVENT(self, Event))
{
/* Translate into Gadget-Relative Coordinates. */
GadgetRelativeCoords( &self->eg.g, Event, &Mouse );
entry_no = (Mouse.y - BORDER_WIDTH) / BROWSER_ENTRY_HEIGHT
+ self->YOffset;
entry_no = MAX( entry_no, 0 );
qual = self->List.Qualifiers[entry_no];
if ( entry_no < self->List.nEntries )
{
if (self->SelectMany)
{
SelectString( self, entry_no, !isSelected(qual) );
ListBrowser_DrawEntry( self,
Event->IDCMPWindow->RPort, entry_no );
}
else
{
if (!isSelected(qual)) /* Only select if not already. */
{ /* (Avoids ugly screen update.) */
ListBrowser_ChangeHighlight( self, entry_no,
Event->IDCMPWindow->RPort );
}
}
}
response = RESPONDED | CHANGED_STATE | CONSUMED_EVENT;
}
break;
}
return response;
}
BOOL ListBrowser_elaborated = FALSE;
struct StringListerClass ListBrowser_Class;
void ListBrowserClass_Init( struct StringListerClass *class )
{
StringListerClass_Init( class );
EmbossedGadgetClass_Init( class );
class->isa = StringListerClass();
class->ClassName = "ListBrowser";
class->CleanUp = ListBrowser_CleanUp;
class->AskSize = ListBrowser_AskSize;
class->SetSize = ListBrowser_SetSize;
class->SizeFlags = GraphicObject_SizeFlagsAll;
class->SetLocation = ListBrowser_SetLocation;
class->Respond = ListBrowser_Respond;
class->Render = ListBrowser_Render;
class->Refresh = ListBrowser_Refresh;
class->AddString = ListBrowser_AddString;
class->DeleteString = ListBrowser_DeleteString;
class->DeleteAllStrings = ListBrowser_DeleteAllStrings;
class->StringList_of = ListBrowser_StringList_of;
class->SelectString = ListBrowser_SelectString;
}
struct StringListerClass *ListBrowserClass( void )
{
if (! ListBrowser_elaborated)
{
ListBrowserClass_Init( &ListBrowser_Class );
ListBrowser_elaborated = TRUE;
}
return &ListBrowser_Class;
}